package com.hd123.rumba.gwt.widget.client;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.DelegatingChangeListenerCollection;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

/**
 * <li>Press F3 or ALT + DOWN single click icon to show date picker
 * <li>The following keys are available in date picker: LEFT, RIGHT, UP, DOWN:
 * select date; CTRL + LEFT, CTRL + RIGHT: select month; CTRL + UP, CTRL + DOWN:
 * select year; SPACE: go to today date; ENTER: accept the currently selected
 * date ESC: cacel selection;
 * <li>Press ENTER in input box to release the focus
 * 
 * @author Debenson
 * 
 */
public class DateBox extends HorizontalPanel implements MouseListener, KeyboardListener {
  /** 日期输入框, 没有合法性检查 */
  private TextBox inputField;
  private String inputFieldId;
  /** 日期选择按扭 */
  private Image imageButton;
  private String imageButtonId;
  /** 时间或日期模式 */
  private String dateFormatter;
  /** 输入法框只读属性, 默认为false */
  private boolean readOnly = false;
  /** 日期输入框的长度 */
  private String inputFiledSize;
  /** 日期选择按扭图片的位置 */
  private String imgUrl;

  private static final String defaultImagLocation = "images/calendar.gif";
  private static final String defaultDateFormatter = "%Y-%m-%d";

  private DelegatingChangeListenerCollection changeListeners;

  public DateBox() {
    this(DateBox.defaultDateFormatter);
  }

  public DateBox(String formatter) {
    this(DateBox.defaultImagLocation, formatter);
  }

  public DateBox(boolean readOnly) {
    this(DateBox.defaultImagLocation, DateBox.defaultDateFormatter, readOnly);
  }

  public DateBox(String imgUrl, String formatter) {
    this(imgUrl, formatter, false);
  }

  public DateBox(String imgUrl, String formatter, boolean readOnly) {
    this.imgUrl = imgUrl;
    this.dateFormatter = formatter;
    this.readOnly = readOnly;

    this.inputField = new TextBox();
    this.inputFieldId = HTMLPanel.createUniqueId();
    DOM.setElementAttribute(this.inputField.getElement(), "id", this.inputFieldId);
    this.inputField.addKeyboardListener(this);
    this.add(this.inputField);
    this.setCellVerticalAlignment(this.inputField, ALIGN_MIDDLE);
    this.inputField.addChangeListener(new ChangeListener() {

      public void onChange(Widget sender) {
        Window.alert("date change found in java");

      }

    });

    this.imageButton = new Image();
    this.imageButtonId = HTMLPanel.createUniqueId();
    this.imageButton.addMouseListener(this);
    DOM.setElementAttribute(this.imageButton.getElement(), "id", this.imageButtonId);
    this.add(this.imageButton);
    this.setCellVerticalAlignment(this.imageButton, ALIGN_MIDDLE);
  }

  protected void onLoad() {
    this.setImgUrl(this.imgUrl);
    this.setReadOnly(this.readOnly);
    if (this.inputFiledSize != null)
      this.setInputFiledSize(this.inputFiledSize);
    DeferredCommand.addCommand(new Command() {
      public void execute() {
        initCalendar(inputFieldId, imageButtonId, dateFormatter);
      }
    });
  }

  protected native void initCalendar(String textId, String buttonId, String formatter) /*-{  
                  var owner = this;
                  
                  function __notifyDateChange() {                 
                    owner.@com.hd123.rumba.gwt.widget.client.DateBox::onJSDateChange()();
                  }
                     
                  $wnd.Calendar.setup( {
                  inputField    : textId,
                  button        : buttonId,
                  ifFormat      : formatter,
                  ondatechange  : __notifyDateChange                              
                  });   
            }-*/;

  private void onJSDateChange() {
    if (changeListeners != null) {
      changeListeners.onChange(getInputField());
    }
  }

  public void addChangeListener(ChangeListener listener) {
    if (changeListeners == null)
      changeListeners = new DelegatingChangeListenerCollection(this, getInputField());
    changeListeners.add(listener);
  }

  public void removeChangeListener(ChangeListener listener) {
    if (changeListeners != null)
      changeListeners.remove(listener);
  }

  public void onMouseDown(Widget arg0, int arg1, int arg2) {
  }

  public void onMouseEnter(Widget sender) {
    if (sender == this.imageButton) {
      sender.setStyleName("dateBoxOnMouseOver");
    }
  }

  public void onMouseLeave(Widget sender) {
    if (sender == this.imageButton) {
      sender.setStyleName("dateBoxOnMouseOut");
    }
  }

  public void onMouseMove(Widget arg0, int arg1, int arg2) {
  }

  public void onMouseUp(Widget arg0, int arg1, int arg2) {
  }

  public TextBox getInputField() {
    return inputField;
  }

  public String getInputFieldId() {
    return inputFieldId;
  }

  public Image getImageButton() {
    return imageButton;
  }

  public String getImageButtonId() {
    return imageButtonId;
  }

  public String getDateFormatter() {
    return dateFormatter;
  }

  public void setDateFormatter(String formatter) {
    this.dateFormatter = formatter;
  }

  public boolean isReadOnly() {
    return readOnly;
  }

  public void setReadOnly(boolean readOnly) {
    this.readOnly = readOnly;
    if (this.readOnly) {
      // this.inputField.setStyleName("dateBoxReadOnly4InputField");
      this.imageButton.setStyleName("dateBoxReadOnly4Picker");
    } else {
      // this.inputField.setStyleName("dateBoxRW4InputField");
      this.imageButton.setStyleName("dateBoxRW4Picker");
    }
    DOM.setElementPropertyBoolean(this.inputField.getElement(), "readOnly", readOnly);
  }

  public static String getDefaultImagLocation() {
    return defaultImagLocation;
  }

  public static String getDefaultDateFormatter() {
    return defaultDateFormatter;
  }

  public String getInputFiledSize() {
    return inputFiledSize;
  }

  public void setInputFiledSize(String inputFiledSize) {
    this.inputFiledSize = inputFiledSize;
    DOM.setElementAttribute(this.inputField.getElement(), "size", this.inputFiledSize);
  }

  public String getImgUrl() {
    return imgUrl;
  }

  public void setImgUrl(String imgUrl) {
    this.imgUrl = imgUrl;
    this.imageButton.setUrl(this.imgUrl);
  }

  public void setDateText(String dateText) {
    this.inputField.setText(dateText);
  }

  public String getDateText() {
    return this.inputField.getText();
  }

  public void focus() {
    Util.focusTextBox(this.inputField);
  }

  public void onKeyDown(Widget sender, char keyCode, int modifiers) {
    if (sender == this.inputField) {
      if (keyCode == KEY_ENTER) {
        this.inputField.setKey((char) KEY_TAB);
      } else if (keyCode == KEY_DOWN && (modifiers & MODIFIER_ALT) != 0
          || keyCode == Util.KEY_DROPDOWN) {
        showDatePicker(DOM.getElementById(this.imageButtonId));
      }
    }
  }

  protected native void showDatePicker(Element element) /*-{
                  if( element != null ) {
                  element.click();     
                  }}-*/;

  public void onKeyPress(Widget sender, char keyCode, int modifiers) {

  }

  public void onKeyUp(Widget sender, char keyCode, int modifiers) {

  }

}
